home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / src / gas-211 / gas / config / cplus-de.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  17.2 KB  |  936 lines

  1. /* Demangler for GNU C++
  2.    Copyright (C) 1989, 1992 Free Software Foundation, Inc.
  3.    written by James Clark (jjc@jclark.uucp)
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* This is for g++ 1.36.1 (November 6 version). It will probably
  20.    require changes for any other version. */
  21.  
  22. /* This file exports one function
  23.  
  24.    char *cplus_demangle (const char *name)
  25.  
  26.    If `name' is a mangled function name produced by g++, then
  27.    a pointer to a malloced string giving a C++ representation
  28.    of the name will be returned; otherwise NULL will be returned.
  29.    It is the caller's responsibility to free the string which
  30.    is returned.
  31.  
  32.    For example,
  33.  
  34.    cplus_demangle ("_foo__1Ai")
  35.  
  36.    returns
  37.  
  38.    "A::foo(int)"
  39.  
  40.    This file imports xmalloc and xrealloc, which are like malloc and
  41.    realloc except that they generate a fatal error if there is no
  42.    available memory. */
  43.  
  44. /* #define nounderscore 1 /* define this is names don't start with _ */
  45.  
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <ctype.h>
  49.  
  50. #if !defined(sequent) && !defined(NeXT)
  51. #include <memory.h>
  52. #else
  53. #define memcpy(s1, s2, n) strncpy(s1, s2, n)
  54. #define memcmp(s1, s2, n) strncmp(s1, s2, n)
  55. #define strchr(s, c) index(s, c)
  56. #endif
  57.  
  58. #if __STDC__ != 1
  59. #define const
  60. #endif
  61.  
  62. #if __STDC__ == 1
  63. extern char *cplus_demangle (const char *type);
  64. #else
  65. extern char *cplus_demangle ();
  66. #endif
  67.  
  68. #if __STDC__ == 1
  69. extern char *xmalloc (int);
  70. extern char *xrealloc (char *, int);
  71. #else
  72. extern char *xmalloc ();
  73. extern char *xrealloc ();
  74. #endif
  75.  
  76. static char **typevec = 0;
  77. static int ntypes = 0;
  78. static int typevec_size = 0;
  79.  
  80. static struct
  81.   {
  82.     const char *in;
  83.     const char *out;
  84.   }
  85.  
  86. optable[] =
  87. {
  88.   "new", " new",
  89.   "delete", " delete",
  90.   "ne", "!=",
  91.   "eq", "==",
  92.   "ge", ">=",
  93.   "gt", ">",
  94.   "le", "<=",
  95.   "lt", "<",
  96.   "plus", "+",
  97.   "minus", "-",
  98.   "mult", "*",
  99.   "negate", "-",
  100.   "trunc_mod", "%",
  101.   "trunc_div", "/",
  102.   "truth_andif", "&&",
  103.   "truth_orif", "||",
  104.   "postincrement", "++",
  105.   "postdecrement", "--",
  106.   "bit_ior", "|",
  107.   "bit_xor", "^",
  108.   "bit_and", "&",
  109.   "bit_not", "~",
  110.   "call", "()",
  111.   "cond", "?:",
  112.   "alshift", "<<",
  113.   "arshift", ">>",
  114.   "component", "->",
  115.   "nop", "",            /* for operator= */
  116. };
  117.  
  118. /* Beware: these aren't '\0' terminated. */
  119.  
  120. typedef struct
  121.   {
  122.     char *b;            /* pointer to start of string */
  123.     char *p;            /* pointer after last character */
  124.     char *e;            /* pointer after end of allocated space */
  125.   }
  126.  
  127. string;
  128.  
  129. #if __STDC__ == 1
  130. static void string_need (string * s, int n);
  131. static void string_delete (string * s);
  132. static void string_init (string * s);
  133. static void string_clear (string * s);
  134. static int string_empty (string * s);
  135. static void string_append (string * p, const char *s);
  136. static void string_appends (string * p, string * s);
  137. static void string_appendn (string * p, const char *s, int n);
  138. static void string_prepend (string * p, const char *s);
  139. #if 0
  140. static void string_prepends (string * p, string * s);
  141. #endif
  142. static void string_prependn (string * p, const char *s, int n);
  143. static int get_count (const char **type, int *count);
  144. static int do_args (const char **type, string * decl);
  145. static int do_type (const char **type, string * result);
  146. static int do_arg (const char **type, string * result);
  147. static int do_args (const char **type, string * decl);
  148. static void munge_function_name (string * name);
  149. #else
  150. static void string_need ();
  151. static void string_delete ();
  152. static void string_init ();
  153. static void string_clear ();
  154. static int string_empty ();
  155. static void string_append ();
  156. static void string_appends ();
  157. static void string_appendn ();
  158. static void string_prepend ();
  159. static void string_prepends ();
  160. static void string_prependn ();
  161. static int get_count ();
  162. static int do_args ();
  163. static int do_type ();
  164. static int do_arg ();
  165. static int do_args ();
  166. static void munge_function_name ();
  167. #endif
  168.  
  169. char *
  170. cplus_demangle (type)
  171.      const char *type;
  172. {
  173.   string decl;
  174.   int n;
  175.   int success = 0;
  176.   int constructor = 0;
  177.   int const_flag = 0;
  178.   int i;
  179.   const char *p;
  180.  
  181.   if (type == NULL || *type == '\0')
  182.     return NULL;
  183. #ifndef nounderscore
  184.   if (*type++ != '_')
  185.     return NULL;
  186. #endif
  187.   p = type;
  188.   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  189.     p++;
  190.   if (*p == '\0')
  191.     {
  192.       /* destructor */
  193.       if (type[0] == '_' && type[1] == '$' && type[2] == '_')
  194.     {
  195.       int n = (strlen (type) - 3) * 2 + 3 + 2 + 1;
  196.       char *tem = (char *) xmalloc (n);
  197.       strcpy (tem, type + 3);
  198.       strcat (tem, "::~");
  199.       strcat (tem, type + 3);
  200.       strcat (tem, "()");
  201.       return tem;
  202.     }
  203.       /* static data member */
  204.       if (*type != '_' && (p = strchr (type, '$')) != '\0')
  205.     {
  206.       int n = strlen (type) + 2;
  207.       char *tem = (char *) xmalloc (n);
  208.       memcpy (tem, type, p - type);
  209.       strcpy (tem + (p - type), "::");
  210.       strcpy (tem + (p - type) + 2, p + 1);
  211.       return tem;
  212.     }
  213.       return NULL;
  214.     }
  215.  
  216.   string_init (&decl);
  217.  
  218.   if (p == type)
  219.     {
  220.       if (!isdigit (p[2]))
  221.     {
  222.       string_delete (&decl);
  223.       return NULL;
  224.     }
  225.       constructor = 1;
  226.     }
  227.   else
  228.     {
  229.       string_appendn (&decl, type, p - type);
  230.       munge_function_name (&decl);
  231.     }
  232.   p += 2;
  233.  
  234.   switch (*p)
  235.     {
  236.     case 'C':
  237.       /* a const member function */
  238.       if (!isdigit (p[1]))
  239.     {
  240.       string_delete (&decl);
  241.       return NULL;
  242.     }
  243.       p += 1;
  244.       const_flag = 1;
  245.       /* fall through */
  246.     case '0':
  247.     case '1':
  248.     case '2':
  249.     case '3':
  250.     case '4':
  251.     case '5':
  252.     case '6':
  253.     case '7':
  254.     case '8':
  255.     case '9':
  256.       n = 0;
  257.       do
  258.     {
  259.       n *= 10;
  260.       n += *p - '0';
  261.       p += 1;
  262.     }
  263.       while (isdigit (*p));
  264.       if (strlen (p) < n)
  265.     {
  266.       string_delete (&decl);
  267.       return NULL;
  268.     }
  269.       if (constructor)
  270.     {
  271.       string_appendn (&decl, p, n);
  272.       string_append (&decl, "::");
  273.       string_appendn (&decl, p, n);
  274.     }
  275.       else
  276.     {
  277.       string_prepend (&decl, "::");
  278.       string_prependn (&decl, p, n);
  279.     }
  280.       p += n;
  281.       success = do_args (&p, &decl);
  282.       if (const_flag)
  283.     string_append (&decl, " const");
  284.       break;
  285.     case 'F':
  286.       p += 1;
  287.       success = do_args (&p, &decl);
  288.       break;
  289.     }
  290.  
  291.   for (i = 0; i < ntypes; i++)
  292.     if (typevec[i] != NULL)
  293.       free (typevec[i]);
  294.   ntypes = 0;
  295.   if (typevec != NULL)
  296.     {
  297.       free ((char *) typevec);
  298.       typevec = NULL;
  299.       typevec_size = 0;
  300.     }
  301.  
  302.   if (success)
  303.     {
  304.       string_appendn (&decl, "", 1);
  305.       return decl.b;
  306.     }
  307.   else
  308.     {
  309.       string_delete (&decl);
  310.       return NULL;
  311.     }
  312. }
  313.  
  314. static int
  315. get_count (type, count)
  316.      const char **type;
  317.      int *count;
  318. {
  319.   if (!isdigit (**type))
  320.     return 0;
  321.   *count = **type - '0';
  322.   *type += 1;
  323.   /* see flush_repeats in cplus-method.c */
  324.   if (isdigit (**type))
  325.     {
  326.       const char *p = *type;
  327.       int n = *count;
  328.       do
  329.     {
  330.       n *= 10;
  331.       n += *p - '0';
  332.       p += 1;
  333.     }
  334.       while (isdigit (*p));
  335.       if (*p == '_')
  336.     {
  337.       *type = p + 1;
  338.       *count = n;
  339.     }
  340.     }
  341.   return 1;
  342. }
  343.  
  344. /* result will be initialised here; it will be freed on failure */
  345.  
  346. static int
  347. do_type (type, result)
  348.      const char **type;
  349.      string *result;
  350. {
  351.   int n;
  352.   int done;
  353.   int non_empty;
  354.   int success;
  355.   string decl;
  356.   const char *remembered_type;
  357.  
  358.   string_init (&decl);
  359.   string_init (result);
  360.  
  361.   done = 0;
  362.   success = 1;
  363.   while (success && !done)
  364.     {
  365.       int member;
  366.       switch (**type)
  367.     {
  368.     case 'P':
  369.       *type += 1;
  370.       string_prepend (&decl, "*");
  371.       break;
  372.  
  373.     case 'R':
  374.       *type += 1;
  375.       string_prepend (&decl, "&");
  376.       break;
  377.  
  378.     case 'T':
  379.       *type += 1;
  380.       if (!get_count (type, &n) || n >= ntypes)
  381.         success = 0;
  382.       else
  383.         {
  384.           remembered_type = typevec[n];
  385.           type = &remembered_type;
  386.         }
  387.       break;
  388.  
  389.     case 'F':
  390.       *type += 1;
  391.       if (!string_empty (&decl) && decl.b[0] == '*')
  392.         {
  393.           string_prepend (&decl, "(");
  394.           string_append (&decl, ")");
  395.         }
  396.       if (!do_args (type, &decl) || **type != '_')
  397.         success = 0;
  398.       else
  399.         *type += 1;
  400.       break;
  401.  
  402.     case 'M':
  403.     case 'O':
  404.       {
  405.         int constp = 0;
  406.         int volatilep = 0;
  407.  
  408.         member = **type == 'M';
  409.         *type += 1;
  410.         if (!isdigit (**type))
  411.           {
  412.         success = 0;
  413.         break;
  414.           }
  415.         n = 0;
  416.         do
  417.           {
  418.         n *= 10;
  419.         n += **type - '0';
  420.         *type += 1;
  421.           }
  422.         while (isdigit (**type));
  423.         if (strlen (*type) < n)
  424.           {
  425.         success = 0;
  426.         break;
  427.           }
  428.         string_append (&decl, ")");
  429.         string_prepend (&decl, "::");
  430.         string_prependn (&decl, *type, n);
  431.         string_prepend (&decl, "(");
  432.         *type += n;
  433.         if (member)
  434.           {
  435.         if (**type == 'C')
  436.           {
  437.             *type += 1;
  438.             constp = 1;
  439.           }
  440.         if (**type == 'V')
  441.           {
  442.             *type += 1;
  443.             volatilep = 1;
  444.           }
  445.         if (*(*type)++ != 'F')
  446.           {
  447.             success = 0;
  448.             break;
  449.           }
  450.           }
  451.         if ((member && !do_args (type, &decl)) || **type != '_')
  452.           {
  453.         success = 0;
  454.         break;
  455.           }
  456.         *type += 1;
  457.         if (constp)
  458.           {
  459.         if (non_empty)
  460.           string_append (&decl, " ");
  461.         else
  462.           non_empty = 1;
  463.         string_append (&decl, "const");
  464.           }
  465.         if (volatilep)
  466.           {
  467.         if (non_empty)
  468.           string_append (&decl, " ");
  469.         else
  470.           non_empty = 1;
  471.         string_append (&decl, "volatilep");
  472.           }
  473.         break;
  474.       }
  475.  
  476.     case 'C':
  477.       if ((*type)[1] == 'P')
  478.         {
  479.           *type += 1;
  480.           if (!string_empty (&decl))
  481.         string_prepend (&decl, " ");
  482.           string_prepend (&decl, "const");
  483.           break;
  484.         }
  485.  
  486.       /* fall through */
  487.     default:
  488.       done = 1;
  489.       break;
  490.     }
  491.     }
  492.  
  493.   done = 0;
  494.   non_empty = 0;
  495.   while (success && !done)
  496.     {
  497.       switch (**type)
  498.     {
  499.     case 'C':
  500.       *type += 1;
  501.       if (non_empty)
  502.         string_append (result, " ");
  503.       else
  504.         non_empty = 1;
  505.       string_append (result, "const");
  506.       break;
  507.     case 'U':
  508.       *type += 1;
  509.       if (non_empty)
  510.         string_append (result, " ");
  511.       else
  512.         non_empty = 1;
  513.       string_append (result, "unsigned");
  514.       break;
  515.     case 'V':
  516.       *type += 1;
  517.       if (non_empty)
  518.         string_append (result, " ");
  519.       else
  520.         non_empty = 1;
  521.       string_append (result, "volatile");
  522.       break;
  523.     default:
  524.       done = 1;
  525.       break;
  526.     }
  527.     }
  528.  
  529.   if (success)
  530.     switch (**type)
  531.       {
  532.       case '\0':
  533.       case '_':
  534.     break;
  535.       case 'v':
  536.     *type += 1;
  537.     if (non_empty)
  538.       string_append (result, " ");
  539.     string_append (result, "void");
  540.     break;
  541.       case 'l':
  542.     *type += 1;
  543.     if (non_empty)
  544.       string_append (result, " ");
  545.     string_append (result, "long");
  546.     break;
  547.       case 'i':
  548.     *type += 1;
  549.     if (non_empty)
  550.       string_append (result, " ");
  551.     string_append (result, "int");
  552.     break;
  553.       case 's':
  554.     *type += 1;
  555.     if (non_empty)
  556.       string_append (result, " ");
  557.     string_append (result, "short");
  558.     break;
  559.       case 'c':
  560.     *type += 1;
  561.     if (non_empty)
  562.       string_append (result, " ");
  563.     string_append (result, "char");
  564.     break;
  565.       case 'r':
  566.     *type += 1;
  567.     if (non_empty)
  568.       string_append (result, " ");
  569.     string_append (result, "long double");
  570.     break;
  571.       case 'd':
  572.     *type += 1;
  573.     if (non_empty)
  574.       string_append (result, " ");
  575.     string_append (result, "double");
  576.     break;
  577.       case 'f':
  578.     *type += 1;
  579.     if (non_empty)
  580.       string_append (result, " ");
  581.     string_append (result, "float");
  582.     break;
  583.       case 'G':
  584.     *type += 1;
  585.     if (!isdigit (**type))
  586.       {
  587.         success = 0;
  588.         break;
  589.       }
  590.     /* fall through */
  591.       case '0':
  592.       case '1':
  593.       case '2':
  594.       case '3':
  595.       case '4':
  596.       case '5':
  597.       case '6':
  598.       case '7':
  599.       case '8':
  600.       case '9':
  601.     n = 0;
  602.     do
  603.       {
  604.         n *= 10;
  605.         n += **type - '0';
  606.         *type += 1;
  607.       }
  608.     while (isdigit (**type));
  609.     if (strlen (*type) < n)
  610.       {
  611.         success = 0;
  612.         break;
  613.       }
  614.     if (non_empty)
  615.       string_append (result, " ");
  616.     string_appendn (result, *type, n);
  617.     *type += n;
  618.     break;
  619.       default:
  620.     success = 0;
  621.     break;
  622.       }
  623.  
  624.   if (success)
  625.     {
  626.       if (!string_empty (&decl))
  627.     {
  628.       string_append (result, " ");
  629.       string_appends (result, &decl);
  630.     }
  631.       string_delete (&decl);
  632.       return 1;
  633.     }
  634.   else
  635.     {
  636.       string_delete (&decl);
  637.       string_delete (result);
  638.       return 0;
  639.     }
  640. }
  641.  
  642. /* `result' will be initialised in do_type; it will be freed on failure */
  643.  
  644. static int
  645. do_arg (type, result)
  646.      const char **type;
  647.      string *result;
  648. {
  649.   char *tem;
  650.   int len;
  651.   const char *start;
  652.   const char *end;
  653.  
  654.   start = *type;
  655.   if (!do_type (type, result))
  656.     return 0;
  657.   end = *type;
  658.   if (ntypes >= typevec_size)
  659.     {
  660.       if (typevec_size == 0)
  661.     {
  662.       typevec_size = 3;
  663.       typevec = (char **) xmalloc (sizeof (char *) * typevec_size);
  664.     }
  665.       else
  666.     {
  667.       typevec_size *= 2;
  668.       typevec = (char **) xrealloc ((char *) typevec, sizeof (char *) * typevec_size);
  669.     }
  670.     }
  671.   len = end - start;
  672.   tem = (char *) xmalloc (len + 1);
  673.   memcpy (tem, start, len);
  674.   tem[len] = '\0';
  675.   typevec[ntypes++] = tem;
  676.   return 1;
  677. }
  678.  
  679. /* `decl' must be already initialised, usually non-empty;
  680.    it won't be freed on failure */
  681.  
  682. static int
  683. do_args (type, decl)
  684.      const char **type;
  685.      string *decl;
  686. {
  687.   string arg;
  688.   int need_comma = 0;
  689.  
  690.   string_append (decl, "(");
  691.  
  692.   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
  693.     {
  694.       if (**type == 'N')
  695.     {
  696.       int r;
  697.       int t;
  698.       *type += 1;
  699.       if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
  700.         return 0;
  701.       while (--r >= 0)
  702.         {
  703.           const char *tem = typevec[t];
  704.           if (need_comma)
  705.         string_append (decl, ", ");
  706.           if (!do_arg (&tem, &arg))
  707.         return 0;
  708.           string_appends (decl, &arg);
  709.           string_delete (&arg);
  710.           need_comma = 1;
  711.         }
  712.     }
  713.       else
  714.     {
  715.       if (need_comma)
  716.         string_append (decl, ", ");
  717.       if (!do_arg (type, &arg))
  718.         return 0;
  719.       string_appends (decl, &arg);
  720.       string_delete (&arg);
  721.       need_comma = 1;
  722.     }
  723.     }
  724.  
  725.   if (**type == 'v')
  726.     *type += 1;
  727.   else if (**type == 'e')
  728.     {
  729.       *type += 1;
  730.       if (need_comma)
  731.     string_append (decl, ",");
  732.       string_append (decl, "...");
  733.     }
  734.  
  735.   string_append (decl, ")");
  736.   return 1;
  737. }
  738.  
  739. static void
  740. munge_function_name (name)
  741.      string *name;
  742. {
  743.   if (!string_empty (name) && name->p - name->b >= 3
  744.       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
  745.     {
  746.       int i;
  747.       /* see if it's an assignment expression */
  748.       if (name->p - name->b >= 10    /* op$assign_ */
  749.       && memcmp (name->b + 3, "assign_", 7) == 0)
  750.     {
  751.       for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
  752.         {
  753.           int len = name->p - name->b - 10;
  754.           if (strlen (optable[i].in) == len
  755.           && memcmp (optable[i].in, name->b + 10, len) == 0)
  756.         {
  757.           string_clear (name);
  758.           string_append (name, "operator");
  759.           string_append (name, optable[i].out);
  760.           string_append (name, "=");
  761.           return;
  762.         }
  763.         }
  764.     }
  765.       else
  766.     {
  767.       for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
  768.         {
  769.           int len = name->p - name->b - 3;
  770.           if (strlen (optable[i].in) == len
  771.           && memcmp (optable[i].in, name->b + 3, len) == 0)
  772.         {
  773.           string_clear (name);
  774.           string_append (name, "operator");
  775.           string_append (name, optable[i].out);
  776.           return;
  777.         }
  778.         }
  779.     }
  780.       return;
  781.     }
  782.   else if (!string_empty (name) && name->p - name->b >= 5
  783.        && memcmp (name->b, "type$", 5) == 0)
  784.     {
  785.       /* type conversion operator */
  786.       string type;
  787.       const char *tem = name->b + 5;
  788.       if (do_type (&tem, &type))
  789.     {
  790.       string_clear (name);
  791.       string_append (name, "operator ");
  792.       string_appends (name, &type);
  793.       string_delete (&type);
  794.       return;
  795.     }
  796.     }
  797. }
  798.  
  799. /* a mini string-handling package */
  800.  
  801. static void
  802. string_need (s, n)
  803.      string *s;
  804.      int n;
  805. {
  806.   if (s->b == NULL)
  807.     {
  808.       if (n < 32)
  809.     n = 32;
  810.       s->p = s->b = (char *) xmalloc (n);
  811.       s->e = s->b + n;
  812.     }
  813.   else if (s->e - s->p < n)
  814.     {
  815.       int tem = s->p - s->b;
  816.       n += tem;
  817.       n *= 2;
  818.       s->b = (char *) xrealloc (s->b, n);
  819.       s->p = s->b + tem;
  820.       s->e = s->b + n;
  821.     }
  822. }
  823.  
  824. static void
  825. string_delete (s)
  826.      string *s;
  827. {
  828.   if (s->b != NULL)
  829.     {
  830.       free (s->b);
  831.       s->b = s->e = s->p = NULL;
  832.     }
  833. }
  834.  
  835. static void
  836. string_init (s)
  837.      string *s;
  838. {
  839.   s->b = s->p = s->e = NULL;
  840. }
  841.  
  842. static void
  843. string_clear (s)
  844.      string *s;
  845. {
  846.   s->p = s->b;
  847. }
  848.  
  849. static int
  850. string_empty (s)
  851.      string *s;
  852. {
  853.   return s->b == s->p;
  854. }
  855.  
  856. static void
  857. string_append (p, s)
  858.      string *p;
  859.      const char *s;
  860. {
  861.   int n;
  862.   if (s == NULL || *s == '\0')
  863.     return;
  864.   n = strlen (s);
  865.   string_need (p, n);
  866.   memcpy (p->p, s, n);
  867.   p->p += n;
  868. }
  869.  
  870. static void
  871. string_appends (p, s)
  872.      string *p, *s;
  873. {
  874.   int n;
  875.   if (s->b == s->p)
  876.     return;
  877.   n = s->p - s->b;
  878.   string_need (p, n);
  879.   memcpy (p->p, s->b, n);
  880.   p->p += n;
  881. }
  882.  
  883. static void
  884. string_appendn (p, s, n)
  885.      string *p;
  886.      const char *s;
  887.      int n;
  888. {
  889.   if (n == 0)
  890.     return;
  891.   string_need (p, n);
  892.   memcpy (p->p, s, n);
  893.   p->p += n;
  894. }
  895.  
  896. static void
  897. string_prepend (p, s)
  898.      string *p;
  899.      const char *s;
  900. {
  901.   if (s == NULL || *s == '\0')
  902.     return;
  903.   string_prependn (p, s, strlen (s));
  904. }
  905.  
  906. #if 0
  907. static void
  908. string_prepends (p, s)
  909.      string *p, *s;
  910. {
  911.   if (s->b == s->p)
  912.     return;
  913.   string_prependn (p, s->b, s->p - s->b);
  914. }
  915.  
  916. #endif
  917.  
  918. static void
  919. string_prependn (p, s, n)
  920.      string *p;
  921.      const char *s;
  922.      int n;
  923. {
  924.   char *q;
  925.  
  926.   if (n == 0)
  927.     return;
  928.   string_need (p, n);
  929.   for (q = p->p - 1; q >= p->b; q--)
  930.     q[n] = q[0];
  931.   memcpy (p->b, s, n);
  932.   p->p += n;
  933. }
  934.  
  935. /* end of cplus-dem.c */
  936.